/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.google.common.collect.Lists;
import com.xxl.job.core.context.XxlJobHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.MaintainTimeSubmitDTO;
import org.springblade.modules.admin.dto.contract.ContractSearchDTO;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.dto.RobotHoverDTO;
import org.springblade.modules.admin.entity.BuildingContractExt;
import org.springblade.modules.admin.entity.BuildingContractPlus;
import org.springblade.modules.admin.entity.ElevatorContract;
import org.springblade.modules.admin.entity.ElevatorDetail;
import org.springblade.modules.admin.enums.ElevatorMaintainStatusEnums;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.*;
import org.springblade.modules.admin.vo.contract.*;
import org.springblade.modules.admin.vo.contract.v2.ContractInTimeVo;
import org.springblade.modules.admin.vo.contract.v2.ContractListVo;
import org.springblade.modules.admin.vo.contract.v2.ContractStatusCountVo;
import org.springblade.modules.admin.vo.defert.PlanConfigVo;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目合同信息 控制器
 *
 * @author ysq
 * @since 2022-03-01
 */
@RestController
@AllArgsConstructor
@RequestMapping("admin/buildingcontractplus")
@Api(value = "项目合同信息", tags = "项目合同信息接口")
public class BuildingContractPlusController extends BladeController {


	private final IBuildingUserService buildingUserService;

	private final IBuildingContractPlusService buildingContractPlusService;

	private final IElevatorContractService elevatorContractService;

	private final IUserService userService;

	private final BuildingService buildingService;

	private final ElevatorService elevatorService;

	private final IElevatorDetailService elevatorDetailService;

	private final IBuildingContractExtPlusService buildingContractExtPlusService;

	private final IBuildingContractMaintainTimeService buildingContractMaintainTimeService;

	private final IMaintainContractTypeService maintainContractTypeService;

	private final IContractLogService contractLogService;

	private final IMaintainPlanContentService maintainPlanContentService;

	private final IMaintainPlanConfigService maintainPlanConfigService;

	private final IContractLogService ontractLogService;

	/**
	 * 合同状态1:未生效2:已生效3:已到期4:已终止,
	 */
	private final Integer[] CONTRACT_STATUS = {0, 1, 2, 3, 4, 5};

	/**
	 * 合同状态的取消
	 *
	 * @param id     合同id
	 * @param status 1:表示取消脱保，2：终止开启，3：作废开启
	 * @return 数据集
	 */
	@GetMapping("/cancel/status")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "取消合同状态")
	public R<Boolean> cancelContract(Long id, Integer status) {

		return R.data(buildingContractPlusService.cancelContract(id, status));
	}


	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入buildingContractPlus")
	public R<BuildingContractPlus> detail(Long id, Integer parentDetailType) {
		/**
		 * 表示查询上级信息
		 */
		Integer detailType = 1;
		BuildingContractPlus detail = buildingContractPlusService.getById(id);
		if (parentDetailType != null && parentDetailType.equals(detailType)) {
			BuildingContractPlus serviceOne = buildingContractPlusService.getOne(Wrappers.<BuildingContractPlus>lambdaQuery().eq(BuildingContractPlus::getParentId, id).last("limit 1"));
			if (serviceOne == null || serviceOne.getParentId() == null) {
				return R.data(null);
			} else {
				detail = serviceOne;
			}
		}
		List<ContractBuildingInfoVo> buildingInfos = new ArrayList<>(16);
		List<ElevatorContract> elevatorContracts = elevatorContractService.list(Wrappers.<ElevatorContract>lambdaQuery().eq(ElevatorContract::getContractId, detail.getId()));
		Map<Long, List<ElevatorDetail>> listMap = buildingContractPlusService.getElevatorDetailList().stream().collect(Collectors.groupingBy(ElevatorDetail::getElevatorId));
		for (ElevatorContract elevatorContract : elevatorContracts) {
			ContractBuildingInfoVo contractBuildingInfoVo = new ContractBuildingInfoVo();
			BeanUtil.copyProperties(elevatorContract, contractBuildingInfoVo);
			if (listMap.get(elevatorContract.getElevatorId()) != null && listMap.get(elevatorContract.getElevatorId()).size() > 0) {
				ElevatorDetail elevatorDetail = listMap.get(elevatorContract.getElevatorId()).get(0);
				contractBuildingInfoVo.setVarietiesEquipment(elevatorDetail.getDriveModeName());
				contractBuildingInfoVo.setElevatorAddress(elevatorDetail.getElevatorAddress());
				contractBuildingInfoVo.setBrandId(Convert.toStr(elevatorDetail.getBrandId(), ""));
				contractBuildingInfoVo.setBrandName(elevatorDetail.getBrandName());
			}

			//处理保养类型名称，后台拼接好给前端
			MaintainContractType contractTypeHistoryInfo = elevatorContract.getContractTypeHistoryInfo();
			if (contractTypeHistoryInfo != null) {
				List<MaintainContractType> list = new ArrayList<>(1);
				list.add(contractTypeHistoryInfo);
				List<MaintainContractType> maintainContractTypes = maintainContractTypeService.contractTypeList(list);
				String name = maintainContractTypes.get(0).getName();
				contractTypeHistoryInfo.setName(name);
				contractBuildingInfoVo.setContractTypeHistoryInfo(contractTypeHistoryInfo);
				contractBuildingInfoVo.setChangeRestrictType(contractTypeHistoryInfo.getChangeRestrictType());
				contractBuildingInfoVo.setExtUrls(contractTypeHistoryInfo.getExtUrls());
			}

			if (elevatorContract.getCustomerUnitId() != null) {
				BuildingUser buildingUser = buildingUserService.getById(elevatorContract.getCustomerUnitId());
				if (buildingUser != null) {
					contractBuildingInfoVo.setCustomerUnitName(buildingUser.getName());
				}
			}

			//查询电梯信息是否完善-针对年审梯有效
			Elevator elevator = elevatorService.getById(elevatorContract.getElevatorId());
			ElevatorDetail elevatorDetail = elevatorDetailService.getOne(Wrappers.<ElevatorDetail>lambdaQuery().eq(ElevatorDetail::getElevatorId, elevatorContract.getElevatorId()));
			contractBuildingInfoVo.setUseType(elevatorDetail.getUseType());
			if (elevatorDetail != null && elevatorDetail.getUseType() == 0) {
				Date endDate = elevator.getBxCompanyEndDate();
				String factoryNumber = elevatorDetail.getFactoryNumber();
				String ccIntact = Convert.toStr(elevator.getSbZcIntact(), "");
				if (endDate != null && factoryNumber != null && ccIntact.equals("1.00")) {
					contractBuildingInfoVo.setIsEleOK(1);
				} else {
					contractBuildingInfoVo.setIsEleOK(2);
				}
			} else {
				contractBuildingInfoVo.setIsEleOK(3);
			}

			Building building = buildingService.getById(elevatorContract.getBuildingId());
			if (building != null) {
				contractBuildingInfoVo.setBuildingType(Convert.toInt(building.getType()));
			}

			//判断是否有剩余排序计划
			MaintainPlanContent one = maintainPlanContentService.getOne(Wrappers.<MaintainPlanContent>lambdaQuery().eq(MaintainPlanContent::getTypeStatus, 1).eq(MaintainPlanContent::getElevatorId, elevatorContract.getElevatorId()).gt(MaintainPlanContent::getPlanDate, new Date()).last("limit 1"));
			contractBuildingInfoVo.setIsPlan(one != null ? 2 : 1);
			buildingInfos.add(contractBuildingInfoVo);


		}
		detail.setElevatorCounts(elevatorContracts.stream().map(ElevatorContract::getElevatorId).distinct().collect(Collectors.toList()).size());
		detail.setBuildingInfo(buildingInfos);
		User user = userService.getById(detail.getMaintainMainUser());
		if (user != null) {
			detail.setMaintainMainUserName(user.getRealName());
			detail.setUserStatus(user.getStatus());
		}
		User user2 = userService.getById(detail.getCreateUser());
		if (user2 != null) {
			detail.setCreateUserName(user2.getRealName());
		}
		if (StrUtil.isEmpty(detail.getCustomerPhone())) {
			BuildingUser buildingUser = buildingUserService.getById(detail.getCustomerUnitId());
			if (buildingUser != null) {
				detail.setCustomerPhone(buildingUser.getName());
			}
		}

		if (detail.getParentId() != null) {
			BuildingContractPlus contractPlus = buildingContractPlusService.getById(detail.getParentId());
			detail.setParentNo(contractPlus.getContractNo());
		}


		//2024-03-11 新增服务内容
		BuildingContractExtPlus contractExtPlus = buildingContractExtPlusService.getOne(Wrappers.<BuildingContractExtPlus>lambdaQuery().eq(BuildingContractExtPlus::getContractId, id));
		if (contractExtPlus != null) {
			List<MaintainTimeSubmitDTO> submitDTOList = buildingContractMaintainTimeService.selectMaintainTimes(id);
			contractExtPlus.setBuildingMaintainTimes(submitDTOList);
		}
		detail.setBuildingContractExtPlus(contractExtPlus);
		return R.data(detail);
	}


	/**
	 * 详情
	 */
	@GetMapping("/detail/plus")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入buildingContractPlus")
	public R<Map<String, BuildingContractPlus>> detailPlus(Long id, Integer parentDetailType) {
		Map<String, BuildingContractPlus> map = new HashMap<>(16);
		BuildingContractPlus data = detail(id, parentDetailType).getData();
		BuildingContractPlus contractPlus = detail(data.getParentId(), parentDetailType).getData();
		map.put("nowContract", data);
		map.put("parentContract", contractPlus);
		return R.data(map);
	}


	@GetMapping("/getDetailByElevator")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "根据电梯id获取最新的合同", notes = "传入buildingContractPlus")
	public R<BuildingContractPlus> getDetailByElevator(Long elevatorId) {
		BuildingContractPlus buildingContractPlus = buildingContractPlusService.getDetailByElevator(elevatorId);
		return R.data(buildingContractPlus);
	}


	/**
	 * 详情
	 */
	@GetMapping("/getContractStatisticInfo")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取合同统计", notes = "传入buildingContractPlus")
	public R<ContractStatisticVo> getContractStatisticInfo() {
		ContractStatisticVo contractStatisticInfo = buildingContractPlusService.getContractStatisticInfo();
		return R.data(contractStatisticInfo);
	}


	/**
	 * 详情
	 */
	@GetMapping("/getContractStatisticInfo/v2")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取合同统计-v2")
	public R<List<ContractStatisticPlusVo>> getContractStatisticInfoV2(Integer type) {
		List<ContractStatisticPlusVo> statisticPlusVos = buildingContractPlusService.getContractStatistic_v2(type);
		return R.data(statisticPlusVos);
	}

	/**
	 * 自定义分页 项目合同信息
	 */
	@PostMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入buildingContractPlus")
	public R<IPage<BuildingContractPlus>> page(@Valid @RequestBody BuildingContractPlusVO buildingContractPlus) {
		Query query = new Query();
		query.setSize(buildingContractPlus.getSize());
		query.setCurrent(buildingContractPlus.getCurrent());
		if (buildingContractPlus.getDisDeleted() == null) {
			buildingContractPlus.setDisDeleted(false);
		}

		IPage<BuildingContractPlus> pages = buildingContractPlusService.selectBuildingContractPlusPage(Condition.getPage(query), buildingContractPlus);
		return R.data(pages);
	}

	/**
	 * 新增或修改 项目合同信息
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入buildingContractPlus")
	public R submit(@Valid @RequestBody BuildingContractPlus buildingContractPlus) {

		if (buildingContractPlus.getCheckUserId() != null) {
			User user = userService.getById(buildingContractPlus.getCheckUserId());
			buildingContractPlus.setAuditorName(user.getRealName());
		}


		if (buildingContractPlus.getCustomerUnitId() != null) {
			BuildingUser buildingUser = buildingUserService.getById(buildingContractPlus.getCustomerUnitId());
			if (buildingUser != null) {
				buildingContractPlus.setCustomerUnit(buildingUser.getName());
			}
		}

		//新增合同校验逻辑--或者待审核
		if (buildingContractPlus.getBuildingInfo() != null && buildingContractPlus.getBuildingInfo().size() > 0) {
			List<Long> eleIds = buildingContractPlus.getBuildingInfo().stream().map(ContractBuildingInfoVo::getElevatorId).collect(Collectors.toList());
			List<PlanConfigVo> configList = maintainPlanConfigService.getPlanConfigVo(eleIds);
			//第一步 判断拟定在保--如果包含不允许创建
			List<PlanConfigVo> list = configList.stream().filter(o -> o.getMaintainStatus() == ElevatorMaintainStatusEnums.DIS_ENABLE.getId() && !o.getContractId().equals(Convert.toLong(buildingContractPlus.getId(), -1L))).collect(Collectors.toList());

			if (list.size() > 0) {
				throw new ServiceException("电梯维保状态存在拟定在保不允许创建,项目名称:" + list.get(0).getBuildingName() + "-电梯名称:" + list.get(0).getElevatorName());
			}

			//第二步判断 是否全部所有的梯，都脱保--都脱保允许创建
			List<PlanConfigVo> list2 = configList.stream().filter(o -> o.getMaintainStatus() == ElevatorMaintainStatusEnums.RELEASE_INSURANCE.getId()).collect(Collectors.toList());
			//包含脱保，又包含在保内或者在保外---不允许创建
			if (list2.size() > 0 && list2.size() < configList.size()) {
				throw new ServiceException("该合同绑定的电梯存在脱保-在保状态的情况不允许,创建项目名称:" + list2.get(0).getBuildingName() + "-电梯名称:" + list2.get(0).getElevatorName());
			}
		}
		return R.status(buildingContractPlusService.addOrUpdate(buildingContractPlus));
	}


	@GetMapping("transfer/check")
	@ApiOperation(value = "合同转审批")
	@Transactional
	public R transferCheck(Long id, Long userId) {
		BuildingContractPlus oldContractPlus = buildingContractPlusService.getById(id);
		BuildingContractPlus contractPlus = new BuildingContractPlus();
		BeanUtil.copyProperties(oldContractPlus, contractPlus);
		if (!Convert.toLong(oldContractPlus.getCheckUserId(), -1L).equals(userId)) {
			contractPlus.setCheckUserId(userId);
			buildingContractPlusService.updateById(contractPlus);
			ontractLogService.saveLogHistory(310, oldContractPlus, contractPlus);
		}
		return R.data(true);
	}


	/**
	 * 移出回收站
	 * 新增或修改 项目合同信息
	 * 2022-10-28 新增合同终止状态，默认为移出回收站
	 * type:1表示移出回收站，默认状态2:表示取消合同终止
	 */
	@PostMapping("/moveDelete")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "移出回收站", notes = "传入buildingContractPlus")
	@Transactional
	public R moveDelete(Long id, @RequestParam(defaultValue = "1") Integer type) {
		//表示取消合同终止
		int stopType = 2;
		BuildingContractPlus contractPlus = buildingContractPlusService.getById(id);
		BuildingContractPlus oldContractPlus = new BuildingContractPlus();
		BeanUtil.copyProperties(contractPlus, oldContractPlus);

		if (contractPlus != null) {
			List<BuildingContractPlus> list = buildingContractPlusService.list(Wrappers.<BuildingContractPlus>lambdaQuery().ne(BuildingContractPlus::getId, id).eq(BuildingContractPlus::getContractNo, contractPlus.getContractNo()).eq(BuildingContractPlus::getDisDeleted, false));
			if (list.size() > 0) {
				throw new ServiceException("存在相同的合同编码");
			}
		}
		List<ElevatorContract> elevatorContracts = elevatorContractService.list(Wrappers.<ElevatorContract>lambdaQuery().eq(ElevatorContract::getContractId, id));
		for (int i = 0; i < elevatorContracts.size(); i++) {
			Long elevatorId = elevatorContracts.get(i).getElevatorId();
			if (buildingContractPlusService.isExistContractByDates(elevatorId, contractPlus.getContractBeginTime(), contractPlus.getContractEndTime(), id, contractPlus.getContractType())) {
				throw new ServiceException("该合同所选电梯,已经生成了其它合同");
			} else {
				if (type == stopType) {
					final long time = System.currentTimeMillis();
					//取消终止需要判断合同的生效状态
					Date contractBeginTime = contractPlus.getContractBeginTime();
					Date contractEndTime = contractPlus.getContractEndTime();
					Date date = new Date();
					if (date.getTime() > contractBeginTime.getTime() && date.getTime() < contractEndTime.getTime()) {
						contractPlus.setContractStatus(CONTRACT_STATUS[2]);
					} else if (date.getTime() > contractEndTime.getTime()) {
						contractPlus.setContractStatus(CONTRACT_STATUS[3]);
					} else if (date.getTime() < contractBeginTime.getTime()) {
						contractPlus.setContractStatus(CONTRACT_STATUS[1]);
					}
					contractPlus.setStopTime(null);
				} else {
					User user = userService.getById(contractPlus.getMaintainMainUser());
					if (user != null) {
						contractPlus.setMaintainMainUserName(user.getRealName());
					}
					BuildingContractExtPlus contractExtPlus = buildingContractExtPlusService.getOne(Wrappers.<BuildingContractExtPlus>lambdaQuery().eq(BuildingContractExtPlus::getContractId, id));
					List<MaintainTimeSubmitDTO> maintainTimeSubmitDTOS = buildingContractMaintainTimeService.selectMaintainTimes(id);
					contractExtPlus.setBuildingMaintainTimes(maintainTimeSubmitDTOS);
					contractPlus.setBuildingContractExtPlus(contractExtPlus);
					contractPlus.setDisDeleted(false);
				}
			}
		}
		buildingContractPlusService.updateById(contractPlus);


		contractLogService.saveLog(oldContractPlus, contractPlus);
		return R.status(true);
	}


	/**
	 * 删除 项目合同信息
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		List<String> asList = Arrays.asList(ids.split(","));
		elevatorContractService.remove(Wrappers.<ElevatorContract>lambdaQuery().in(ElevatorContract::getContractId, asList));
		return R.status(buildingContractPlusService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 删除 项目合同信息
	 */
	@PostMapping("/batchCheck")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "批量审核")
	public R batchCheck(@RequestParam String ids, Integer status, String statusDesc) {
		List<String> asList = Arrays.asList(ids.split(","));
		for (int i = 0; i < asList.size(); i++) {
			BuildingContractPlus buildingContractPlus = new BuildingContractPlus();
			buildingContractPlus.setId(Convert.toLong(asList.get(i)));
			buildingContractPlus.setStatus(status);
			buildingContractPlus.setStatusDesc(statusDesc);
			buildingContractPlusService.addOrUpdate(buildingContractPlus);
		}
		return R.status(true);
	}

	/**
	 * 分页,传入buildingId
	 */
	@GetMapping("elevator/info")
	@ApiOperation(value = "合同电梯信息")
	public R<IPage<ElevatorVO>> page(Query query, Long id, Long buildingId) {

		List<ElevatorContract> list = elevatorContractService.list(Wrappers.<ElevatorContract>lambdaQuery().eq(ElevatorContract::getContractId, id).eq(ElevatorContract::getBuildingId, buildingId));
		List<Long> ids = list.stream().map(ElevatorContract::getElevatorId).collect(Collectors.toList());
		if (ids.size() == 0) {
			throw new ServiceException("该合同没有对应的电梯信息");
		}
		IPage<ElevatorVO> pages = elevatorService.selectElevatorPage(Condition.getPage(query), ids);
		return R.data(pages);
	}


	@PostMapping("/down/excel")
	public void downExcel(HttpServletResponse response, @RequestBody BuildingContractPlusVO buildingContractPlus) throws IOException {

		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("合同编号", "合同来源", "合同类型", "合同属性", "客户单位", "客户电话", "是否为外包合同",
				"维保单位", "签约人", "合同开始", "合同结束", "是否驻场", "年检费用合计", "限速器年检费", "月保养费用", "付款周期", "合同总额", "支付方式", "票据类型", "备注信息");
			List<BuildingContractPlus> buildingContractPluses = buildingContractPlusService.downExcel(buildingContractPlus);
			final List<Integer> integers = buildingContractPluses.stream().map(o -> o.getBuildingInfo().size()).collect(Collectors.toList());
			List<ContractBuildingInfoVo> buildingList = new ArrayList<>(50);
			for (BuildingContractPlus buildingContractPlus1 : buildingContractPluses) {
				buildingList.addAll(buildingContractPlus1.getBuildingInfo());
			}
			final List<Long> buildingIds = buildingList.stream().map(ContractBuildingInfoVo::getBuildingId).distinct().collect(Collectors.toList());
			final List<BuildingVO> buildingVOS = buildingService.selectBuildingByIds(buildingIds);
			final Map<Long, List<BuildingVO>> map = buildingVOS.stream().collect(Collectors.groupingBy(BuildingVO::getId));

			final Integer max = integers.stream().max(Comparator.comparing(Integer::intValue)).get();
			for (int i = 0; i < max; i++) {
				title.add("项目名称");
				title.add("项目地址");
				title.add("项目类型");
				title.add("电梯数量");
			}
			rows.add(title);
			for (BuildingContractPlus buildingContractPlus1 : buildingContractPluses) {
				List<ContractBuildingInfoVo> buildingInfo = buildingContractPlus1.getBuildingInfo();
				List<String> row = new ArrayList<>();
				row.add(Convert.toStr(buildingContractPlus1.getContractNo(), ""));
				row.add(BuildingContractPlusEnums.getContractSourceName(Convert.toInt(buildingContractPlus1.getContractSource(), 0)));
				row.add(BuildingContractPlusEnums.getcontractTypeName(Convert.toInt(buildingContractPlus1.getContractType(), 0)));
				Integer isQuaGuarantee = buildingContractPlus1.getIsQuaGuarantee();
				if (1 == isQuaGuarantee) {
					row.add(Convert.toStr("质保合同"));
				} else if (0 == isQuaGuarantee) {
					row.add(Convert.toStr("非质保合同"));
				} else {
					row.add(Convert.toStr(" "));
				}
				row.add(Convert.toStr(buildingContractPlus1.getCustomerUnit(), ""));
				row.add(Convert.toStr(buildingContractPlus1.getCustomerPhone(), ""));
				row.add(Convert.toInt(buildingContractPlus1.getFromType(), 0) == 1 ? "外包合同" : "非外包合同");
				row.add(Convert.toStr(buildingContractPlus1.getMaintainUnit(), ""));
				row.add(Convert.toStr(buildingContractPlus1.getMaintainMainUserName(), ""));
				row.add(DateUtil.format(buildingContractPlus1.getContractBeginTime(), "yyyy-MM-dd"));
				row.add(DateUtil.format(buildingContractPlus1.getContractEndTime(), "yyyy-MM-dd"));
				row.add(Convert.toInt(buildingContractPlus1.getIsLive(), 0) == 2 ? "需要" : "不限");
				row.add(Convert.toStr(buildingContractPlus1.getYearCostDesc(), "") + "元/" + BuildingContractPlusEnums.getCostTypeName(Convert.toInt(buildingContractPlus1.getYearCostType(), 0)));
				row.add(Convert.toStr(buildingContractPlus1.getYearSpeedGovernorCost(), "") + "元/" + BuildingContractPlusEnums.getCostTypeName(Convert.toInt(buildingContractPlus1.getYearSpeedGovernorCostType(), 0)));
				row.add(Convert.toStr(buildingContractPlus1.getMonthCostDesc() + "/元"));
				row.add(BuildingContractPlusEnums.getpayDateDescName(Convert.toInt(buildingContractPlus1.getPayDateDesc(), 0)) + "/" + BuildingContractPlusEnums.getpayDateTypeName(Convert.toInt(buildingContractPlus1.getPayDateType(), 0)));
				row.add(Convert.toStr(buildingContractPlus1.getContractCost() + "/元"));
				row.add(BuildingContractPlusEnums.getpayTypeName(Convert.toInt(buildingContractPlus1.getPayType(), 0)));
				row.add(BuildingContractPlusEnums.getInvoiceTypeName(Convert.toInt(buildingContractPlus1.getInvoiceType(), 0)));
				row.add(Convert.toStr(buildingContractPlus1.getContractDesc(), ""));
				List<String> buildNames = new ArrayList<>(12);
				for (ContractBuildingInfoVo contractBuildingInfoVo : buildingInfo) {
					List<BuildingVO> buildingVOS1 = map.get(contractBuildingInfoVo.getBuildingId());
					if (buildingVOS1 == null) {
						continue;
					}
					BuildingVO building = buildingVOS1.get(0);
					if (building == null) {
						continue;
					}
					if (buildNames.contains(building.getName())) {
						continue;
					}
					row.add(Convert.toStr(building.getName(), ""));
					row.add(Convert.toStr(building.getLocationAddress(), ""));
					row.add(Convert.toStr(building.getTypeName(), ""));
					row.add(contractBuildingInfoVo.getElevatorCounts().toString());
					buildNames.add(building.getName());
				}
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}


	/**
	 * 下载脱保的Excel
	 *
	 * @param response
	 * @throws IOException
	 */
	@PostMapping("/down/excel/v2")
	public void downExcel_v2(HttpServletResponse response) throws IOException {

		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("项目ID", "项目名称", "电梯ID", "电梯", "电梯识别码", "项目地址", "省", "市", "镇区", "所属责任人",
				"上份合同ID", "上份审核状态", "上份合同创建时间", "上份合同开始时间", "上份合同结束时间", "上份合同是否排班",
				"当前合同ID", "当前合同审核状态", "当前合同创建时间", "当前合同开始时间", "当前合同结束时间", "当前合同是否排班", "当前合同电梯维保状态",
				"续签合同ID", "续签审核状态", "续签合同创建时间", "续签合同开始时间", "续签合同结束时间", "续签合同是否排班"
			);
			rows.add(title);
			List<ConEleDisposableVo> conEleDisposableVos = buildingContractPlusService.downExcel();

			for (ConEleDisposableVo conEleDisposableVo : conEleDisposableVos) {
				List<String> row = new ArrayList<>(16);
				row.add(Convert.toStr(conEleDisposableVo.getBuildingId(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getBuildingName(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getElevatorId(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getElevatorAddress(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getElevatorNum(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getAddress(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getProvinceName(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getCityName(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getAdName(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getRealNames(), "-"));


				row.add(Convert.toStr(conEleDisposableVo.getLastContractId(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getLastStatus(), "-"));
				if (conEleDisposableVo.getLastCreateTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getLastCreateTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getLastContractBeginTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getLastContractBeginTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getLastContractEndTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getLastContractEndTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				row.add(Convert.toBool(conEleDisposableVo.getLastIsPlan(), false) == true ? "是" : "否");


				row.add(Convert.toStr(conEleDisposableVo.getNowContractId(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getNowStatus(), "-"));
				if (conEleDisposableVo.getNowCreateTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNowCreateTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getNowContractBeginTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNowContractBeginTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getNowContractEndTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNowContractEndTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				row.add(Convert.toBool(conEleDisposableVo.getNowIsPlan(), false) == true ? "是" : "否");
				row.add(Convert.toStr(conEleDisposableVo.getMaintainStatus(), "-1"));


				row.add(Convert.toStr(conEleDisposableVo.getNextContractId(), "-"));
				row.add(Convert.toStr(conEleDisposableVo.getNextStatus(), "-"));
				if (conEleDisposableVo.getNextCreateTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNextCreateTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getNextContractBeginTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNextContractBeginTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				if (conEleDisposableVo.getNextContractEndTime() != null) {
					row.add(DateUtil.format(conEleDisposableVo.getNextContractEndTime(), "yyyy-MM-dd HH:mm:ss"));
				} else {
					row.add("-");
				}
				row.add(Convert.toBool(conEleDisposableVo.getNextIsPlan(), false) == true ? "是" : "否");
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}


	/**
	 * 功能描述: 发送响应流方法
	 */
	private void setResponseHeader(HttpServletResponse response, String fileName) {
		try {
			try {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			response.setContentType("application/octet-stream;charset=ISO8859-1");
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			response.addHeader("Pargam", "no-cache");
			response.addHeader("Cache-Control", "no-cache");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * hover 结构拆分，hover的时候再请求
	 *
	 * @return Hover 结构
	 */
	@GetMapping("/list/hover")
	@ApiOperation("hover结构拆分")
	@ApiOperationSupport(order = 35)
	public R<List<ContractBuildingHoverVo>> getHoverList(Long contractId) {
		List<ContractBuildingHoverVo> result = buildingContractPlusService.getHoverList(contractId);
		return R.data(result);
	}


	/**
	 * 以下为2024-03-07版本的需求迭代
	 *
	 * @return
	 */
	@GetMapping("/elevator/states")
	@ApiOperation("合同电梯在保统计信息")
	@ApiOperationSupport(order = 35)
	public R<ContractElevatorStatesVo> getContractElevatorStates() {

		ContractElevatorStatesVo contractElevatorStatesVo = buildingContractPlusService.getContractElevatorStates();
		return R.data(contractElevatorStatesVo);
	}


	@PostMapping("check/elevator/time")
	@ApiOperation("校验合同日期是否连贯")
	@ApiOperationSupport(order = 35)
	public R<Object> checkContractTime(@RequestBody List<ContractCheckTimeVo> contractCheckTimeVos) {
		List<ContractCheckTimeVo> list = new ArrayList<>(16);
		List<Long> eleIds = contractCheckTimeVos.stream().map(ContractCheckTimeVo::getEleId).collect(Collectors.toList());
		List<MaintainPlanConfig> configList = maintainPlanConfigService.list(Wrappers.<MaintainPlanConfig>lambdaQuery().in(MaintainPlanConfig::getElevatorId, eleIds));
		if (configList.size() == 0) {
			return R.data(list);
		}

		//如果全部是有脱保和拟定在保，不校验时间连贯
		List<MaintainPlanConfig> list1 = configList.stream().filter(o -> o.getMaintainStatus() == ElevatorMaintainStatusEnums.RELEASE_INSURANCE.getId() || o.getMaintainStatus() == ElevatorMaintainStatusEnums.DIS_ENABLE.getId()).collect(Collectors.toList());
		if (list1.size() == configList.size()) {
			return R.data(list);
		}
		for (ContractCheckTimeVo contractCheckTimeVo : contractCheckTimeVos) {
			ElevatorContract elevatorContract = elevatorContractService.getLastOfelevatorId(contractCheckTimeVo.getEleId(), contractCheckTimeVo.getContractId());
			if (elevatorContract != null) {
				if (!elevatorContract.getContractId().equals(Convert.toLong(contractCheckTimeVo.getContractId(), 0L))) {
					if (contractCheckTimeVo.getBeginTime().getTime() < elevatorContract.getContractEndTime().getTime()) {
						return R.data(1);
					}
					long between = DateUtil.betweenDay(elevatorContract.getContractEndTime(), contractCheckTimeVo.getBeginTime(), true);
					contractCheckTimeVo.setStatus(between == 1 ? 1 : 2);
					if (between > 1) {
						BuildingContractPlus buildingContractPlus = buildingContractPlusService.getById(elevatorContract.getContractId());
						contractCheckTimeVo.setContractNo(buildingContractPlus.getContractNo());
						list.add(contractCheckTimeVo);
					}
				}
			}

		}
		return R.data(list);
	}


	@GetMapping("check/elevator")
	@ApiOperation("校验电梯完整度")
	@ApiOperationSupport(order = 35)
	public R<List<ConCheckEleInfoVo>> checkElevaotor(String eleIds) {
		List<ConCheckEleInfoVo> list = new ArrayList<>(16);
		String[] split = eleIds.split(",");
		for (int i = 0; i < split.length; i++) {
			Long eleId = Convert.toLong(split[i]);
			ConCheckEleInfoVo conCheckEleInfoVo = new ConCheckEleInfoVo();
			conCheckEleInfoVo.setEleId(eleId);
			Elevator elevator = elevatorService.getById(eleId);
			ElevatorDetail elevatorDetail = elevatorDetailService.getOne(Wrappers.<ElevatorDetail>lambdaQuery().eq(ElevatorDetail::getElevatorId, eleId));
			if (elevatorDetail != null && elevatorDetail.getUseType() == 0) {
				Date endDate = elevator.getBxCompanyEndDate();
				String factoryNumber = elevatorDetail.getFactoryNumber();
				String ccIntact = Convert.toStr(elevator.getSbZcIntact(), "");
				if (endDate != null && factoryNumber != null && ccIntact.equals("1.00")) {
					conCheckEleInfoVo.setEleInfoDesc("已完善");
					conCheckEleInfoVo.setType(1);
				} else {
					conCheckEleInfoVo.setEleInfoDesc("未完善");
					conCheckEleInfoVo.setType(2);
				}
			} else {
				conCheckEleInfoVo.setEleInfoDesc("--");
				conCheckEleInfoVo.setType(3);
			}
			//判断是否有剩余排序计划
			MaintainPlanContent one = maintainPlanContentService.getOne(Wrappers.<MaintainPlanContent>lambdaQuery().eq(MaintainPlanContent::getTypeStatus, 1).eq(MaintainPlanContent::getElevatorId, eleId).gt(MaintainPlanContent::getPlanDate, new Date()).last("limit 1"));
			conCheckEleInfoVo.setIsPlan(one != null ? 2 : 1);
			list.add(conCheckEleInfoVo);
		}
		return R.data(list);
	}

	@GetMapping("init")
	@ApiOperation("数据初始化")
	@ApiOperationSupport(order = 35)
	public R<String> init() {
		buildingContractPlusService.init();
		return R.data("成功");
	}


	@PostMapping("getContractStatistic/disCount")
	@ApiOperation("待续签合同统计")
	public R<ContractStatusCountVo> getContractStatistic(@RequestBody ContractSearchDTO contractSearchDTO) {
		return R.data(buildingContractPlusService.getContractStatistic(contractSearchDTO));
	}

	@PostMapping("disCount/list")
	@ApiOperation("待续签合同列表")
	public R<IPage<ContractListVo>> getContractStatisticList(@RequestBody ContractSearchDTO contractSearchDTO) {
		return R.data(buildingContractPlusService.getContractStatisticList(contractSearchDTO));
	}


	@PostMapping("disCount/list/down")
	@ApiOperation("待续签合同列表下载")
	public void disCountDownExcel(HttpServletResponse response, @RequestBody ContractSearchDTO contractSearchDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("合同编号", "合同管理状态", "合同状态", "负责商务", "项目名称", "电梯数", "合同开始时间", "合同结束时间", "终止时间", "超时未续签", "距离合同到期", "签约人");
			rows.add(title);
			contractSearchDTO.setSize(0);
			IPage<ContractListVo> page = buildingContractPlusService.getContractStatisticList(contractSearchDTO);
			for (ContractListVo record : page.getRecords()) {
				List<String> row = new ArrayList<>();
				row.add(Convert.toStr(record.getContractNo()));
				row.add(Convert.toStr(getContractExtStatusName(record.getContractExtStatus())));
				row.add(Convert.toStr(getContractStatusName(record.getContractStatus())));
				row.add(Convert.toStr(record.getUserName(), ""));
				row.add(Convert.toStr(record.getBuildingName(), ""));
				row.add(Convert.toStr(record.getEleCounts(), "0"));
				row.add(DateUtil.format(record.getContractBeginTime(), "yyyy-MM-dd"));
				row.add(DateUtil.format(record.getContractEndTime(), "yyyy-MM-dd"));
				if (record.getStopTime() != null) {
					row.add(DateUtil.format(record.getStopTime(), "yyyy-MM-dd"));
				} else {
					row.add("-");
				}
				row.add(Convert.toStr(record.getEndDayDesc()));
				row.add(Convert.toStr(record.getAboutEndDayDesc()));
				row.add(Convert.toStr(record.getMaintainMainUserName()));
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}


	@PostMapping("disCheck/list")
	@ApiOperation("待审核合同列表")
	public R<IPage<ContractListVo>> getContractDisCheckList(@RequestBody ContractSearchDTO contractSearchDTO) {
		return R.data(buildingContractPlusService.getContractDisCheckList(contractSearchDTO));
	}

	@PostMapping("disCheck/down")
	@ApiOperation("待审核合同列表下载")
	public void disCheckDwonExcel(HttpServletResponse response, @RequestBody ContractSearchDTO contractSearchDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("合同编号", "审核状态", "负责商务", "项目名称", "电梯数", "合同开始时间", "合同结束时间", "等待审核时间", "签约人", "审批人");
			rows.add(title);
			contractSearchDTO.setSize(0);
			IPage<ContractListVo> page = buildingContractPlusService.getContractDisCheckList(contractSearchDTO);
			for (ContractListVo record : page.getRecords()) {
				List<String> row = new ArrayList<>();
				row.add(Convert.toStr(record.getContractNo()));
				Integer status = Convert.toInt(record.getStatus(), -1);
				if (status == 1) {
					row.add("待审核");
				} else if (status == 2) {
					row.add("审核通过");
				} else if (status == 3) {
					row.add("审核未通过");
				} else {
					row.add("-");
				}
				row.add(Convert.toStr(record.getUserName(), ""));
				row.add(Convert.toStr(record.getBuildingName(), ""));
				row.add(Convert.toStr(record.getEleCounts(), "0"));
				row.add(DateUtil.format(record.getContractBeginTime(), "yyyy-MM-dd"));
				row.add(DateUtil.format(record.getContractEndTime(), "yyyy-MM-dd"));
				row.add(record.getDisCheckDayDesc());
				row.add(Convert.toStr(record.getMaintainMainUserName(), ""));
				row.add(Convert.toStr(record.getCheckUserName(), ""));
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}

	}


	@PostMapping("inTime/list")
	@ApiOperation("服务电梯合同列表")
	public R<IPage<ContractInTimeVo>> getContractInTimeList(@RequestBody ContractSearchDTO contractSearchDTO) {
		return R.data(buildingContractPlusService.getContractInTimeList(contractSearchDTO));
	}

	@PostMapping("inTime/dow")
	@ApiOperation("服务电梯合同列表下载")
	public void inTimeDown(HttpServletResponse response, @RequestBody ContractSearchDTO contractSearchDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("合同编号", "合同业务状态", "变更状态", "负责商务", "项目名称", "电梯数", "审核时间", "合同开始时间", "合同结束时间", "终止时间", "丢保时间", "变更时间", "质保类型", "是否包含免保电梯", "是否收费合同", "签约人");
			rows.add(title);
			contractSearchDTO.setSize(0);
			IPage<ContractInTimeVo> page = buildingContractPlusService.getContractInTimeList(contractSearchDTO);
			for (ContractInTimeVo record : page.getRecords()) {
				List<String> row = new ArrayList<>();
				row.add(Convert.toStr(record.getContractNo()));
				row.add(Convert.toStr(record.getAllStatusDesc()));
				row.add(record.getChangeTime() == null ? "未变更" : "已变更");
				row.add(Convert.toStr(record.getUserName(), ""));
				row.add(Convert.toStr(record.getBuildingName(), ""));
				row.add(Convert.toStr(record.getEleCounts(), "0"));
				if (record.getCheckTime() == null) {
					row.add("-");
				} else {
					row.add(DateUtil.format(record.getCheckTime(), "yyyy-MM-dd"));
				}
				row.add(DateUtil.format(record.getContractBeginTime(), "yyyy-MM-dd"));
				row.add(DateUtil.format(record.getContractEndTime(), "yyyy-MM-dd"));
				row.add(record.getStopTime() == null ? "-" : DateUtil.format(record.getStopTime(), "yyyy-MM-dd"));
				row.add(record.getTuoDate() == null ? "-" : DateUtil.format(record.getTuoDate(), "yyyy-MM-dd"));
				row.add(record.getChangeTime() == null ? "-" : DateUtil.format(record.getChangeTime(), "yyyy-MM-dd"));
				if (Convert.toInt(record.getIsQuaGuarantee(), 0) == 1) {
					row.add("质保合同");
				}
				if (record.getIsQuaGuarantee() == 0) {
					row.add("非质保合同");
				}
				row.add(Convert.toStr(record.getMaintainTypeName(), "-1").contains("免保") ? "含免保电梯" : "不含免保电梯");
				BigDecimal bigDecimal = Convert.toBigDecimal(record.getContractCost(), Convert.toBigDecimal(0));
				if (bigDecimal.compareTo(Convert.toBigDecimal(0)) == 0) {
					row.add("免费合同");
				} else {
					row.add("非免费合同");
				}
				row.add(Convert.toStr(record.getMaintainMainUserName(), ""));
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}

	}


	@PostMapping("tuo/list")
	@ApiOperation("丢保合同统计合同列表")
	public R<IPage<ContractListVo>> getContractTuoList(@RequestBody ContractSearchDTO contractSearchDTO) {
		return R.data(buildingContractPlusService.getContractTuoList(contractSearchDTO));
	}


	@PostMapping("tuo/down")
	@ApiOperation("丢保合同列表下载")
	public void tuoDwonExcel(HttpServletResponse response, @RequestBody ContractSearchDTO contractSearchDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("合同编号", "负责商务", "项目名称", "电梯数", "合同开始时间", "合同到期时间", "终止时间", "丢保时间", "合同状态", "合同管理状态", "丢保原因", "签约人");
			rows.add(title);
			contractSearchDTO.setSize(0);
			IPage<ContractListVo> page = buildingContractPlusService.getContractTuoList(contractSearchDTO);
			for (ContractListVo record : page.getRecords()) {
				List<String> row = new ArrayList<>();
				row.add(Convert.toStr(record.getContractNo()));
				row.add(Convert.toStr(record.getUserName()));
				row.add(Convert.toStr(record.getBuildingName()));
				row.add(Convert.toStr(record.getEleCounts()));
				row.add(DateUtil.format(record.getContractBeginTime(), "yyyy-MM-dd"));
				row.add(DateUtil.format(record.getContractEndTime(), "yyyy-MM-dd"));
				row.add(record.getStopTime() == null ? "-" : DateUtil.format(record.getStopTime(), "yyyy-MM-dd"));
				row.add(record.getTuoDate() == null ? "-" : DateUtil.format(record.getTuoDate(), "yyyy-MM-dd"));
				row.add(getContractStatusName(record.getContractStatus()));
				row.add(getContractExtStatusName(record.getContractExtStatus()));
				Integer anInt = Convert.toInt(record.getTuoType(), -1);
				if (anInt == 1) {
					row.add("服务不达标");
				} else if (anInt == 2) {
					row.add("竞对签约");
				} else if (anInt == 3) {
					row.add("客户暂停使用电梯");
				} else if (anInt == 4 || anInt == -1) {
					row.add("其他-" + record.getTuoTypeDesc());
				} else {
					row.add("-");
				}
				row.add(Convert.toStr(record.getMaintainMainUserName()));
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}

	}


	private String getContractExtStatusName(Integer status) {
		status = Convert.toInt(status, -1);
		if (status == 1) {
			return "待续签";
		}
		if (status == 2) {
			return "已续签";
		}
		if (status == 3) {
			return "即将到期";
		}
		if (status == 4) {
			return "已脱保";
		}
		if (status == 5) {
			return "已作废";
		}
		return "-";
	}

	private String getContractStatusName(Integer status) {
		status = Convert.toInt(status, -1);
		if (status == 1) {
			return "未生效";
		}
		if (status == 2) {
			return "已生效";
		}
		if (status == 3) {
			return "已到期";
		}
		if (status == 4) {
			return "已终止";
		}
		return "-";
	}
}
